/*****************************************************************************
* Keppe Messenger (KMP) Keppe Project-Team User Messaging System
* Copyright (C) 2013-2014 Keppe Project-Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/

#include "frmLogin.h"
#include "frmProfile.h"
#include "ui_frmProfile.h"
#include <QDesktopServices>
#ifdef QT5
#include <QStandardPaths>
#endif
#include <KPTFileDialog>
#include <QImageReader>
#include <QPushButton>
#include <QMessageBox>
#include <QDialog>
#include <QDebug>
#include <QDir>
QImage imgAvatar;

frmProfile::frmProfile(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::frmProfile)
{
    setWindowFlags(windowFlags()^Qt::WindowContextHelpButtonHint);
    ui->setupUi(this);
#ifdef MACX
    this->setMinimumSize(325,350);
    this->setMaximumSize(325,350);
    this->resize(325,350);
#else
#ifdef UNIX
    this->setMinimumSize(325,350);
    this->setMaximumSize(325,350);
    this->resize(325,350);
#endif
#endif
    ui->bbOptions->button(QDialogButtonBox::Apply)->setText(QApplication::tr("Change"));
    ui->bbOptions->button(QDialogButtonBox::Cancel)->setFocus();
}

frmProfile::~frmProfile()
{
    delete ui;
}

void frmProfile::setForm(frmLogin* login)
{
    form = login;
    ui->labAvatar->setText(QApplication::tr("Avatar: %1").arg("ID " + login->getUserAvatar().mid(0,1)));
}

void frmProfile::setData(QString account_, QString nick_, QString message_, QString contacts_)
{
    ui->labName->setText(QApplication::tr("Account: %1").arg(account_));
    ui->txtNick->setText(nick_);
    ui->txtMsgState->setText(QString::fromUtf8(fromMessage(message_)));
    ui->labContacts->setText(QApplication::tr("Contacts: %1").arg(contacts_));
    account = account_;
    nick = nick_;
    message = message_;
    contacts = contacts_;
}

void frmProfile::on_cmdAbort_clicked()
{
    this->close();
}

void frmProfile::on_cmdOK_clicked()
{
    frmLogin *login = (frmLogin*)form;
    if (login->isConnectedWithServer())
    {
        QString nick = ui->txtNick->text();
        QByteArray msgstateunconverted = ui->txtMsgState->text().toUtf8();
        QString msgstate = convertMessage(msgstateunconverted);
        if (nick.length() >= 3)
        {
            if (nick.trimmed() == nick)
            {
                if (nick.contains("\n") || nick.contains("\r") || nick.contains("<br>"))
                {
                    QMessageBox::warning(this,QApplication::tr("Change name"), QApplication::tr("The new name contains CR or LF in binary form!"));
                    return;
                }
            }
            else
            {
                QMessageBox::warning(this,QApplication::tr("Change name"), QApplication::tr("The new name is not the same in trimmed and not trimmed form!"));
                return;
            }
            if (QString::fromUtf8(nick.toUtf8()) != QString::fromLatin1(nick.toUtf8()))
            {
                QMessageBox::warning(this,QApplication::tr("Change name"), QApplication::tr("The new name is not \"UTF-8 without BOM\" compatible!"));
                return;
            }
            if (QString::fromUtf8(nick.toUtf8()) != QString::fromUtf8(nick.toLatin1()))
            {
                QMessageBox::warning(this,QApplication::tr("Change name"), QApplication::tr("The new name is not \"UTF-8 without BOM\" compatible!"));
                return;
            }
        }
        else
        {
            QMessageBox::warning(this,QApplication::tr("Change name"), QApplication::tr("The new name is shorter than %1 bytes!").arg("3"));
            return;
        }
        if (msgstate.trimmed() == msgstate)
        {
            if (msgstate.contains("\n") || msgstate.contains("\r") || msgstate.contains("<br>") || msgstateunconverted.contains("<br>"))
            {
                QMessageBox::warning(this,QApplication::tr("Change message state"), QApplication::tr("The new message state contains CR or LF in binary form!"));
                return;
            }
        }
        else
        {
            QMessageBox::warning(this,QApplication::tr("Change message state"), QApplication::tr("The new message state is not the same in trimmed and not trimmed form!"));
            return;
        }
        if (QString::fromUtf8(msgstate.toUtf8()) != QString::fromLatin1(msgstate.toUtf8()))
        {
            QMessageBox::warning(this,QApplication::tr("Change message state"), QApplication::tr("The new message state is not \"UTF-8 without BOM\" compatible!"));
            return;
        }
        if (QString::fromUtf8(msgstate.toUtf8()) != QString::fromUtf8(msgstate.toLatin1()))
        {
            QMessageBox::warning(this,QApplication::tr("Change message state"), QApplication::tr("The new message state is not \"UTF-8 without BOM\" compatible!"));
            return;
        }
        int retn = login->setUserNick(nick);
        if (retn != 200)
        {
            QMessageBox::warning(this,QApplication::tr("Change name"),QApplication::tr("Name could not be changed with Error %1!").arg(QString::number(retn)));
            return;
        }
        login->updateWelcomeLabel(nick);
        int retm = login->setUserMessageState(msgstate);
        if (retm != 200)
        {
            QMessageBox::warning(this,QApplication::tr("Change message state"),QApplication::tr("Status could not be changed with Error %1!").arg(QString::number(retm)));
            return;
        }
        this->close();
    }
    else
    {
        QMessageBox::information(this,QApplication::tr("Offline"),QApplication::tr("You are offline, please wait until you're online!"));
    }
}

QString frmProfile::convertMessage(QByteArray message)
{
    QString text = QString::fromUtf8(message);
    text.replace(QString::fromUtf8("&"),"&amp;");
    text.replace(QString::fromUtf8("<"),"&lt;");
    text.replace(QString::fromUtf8(">"),"&gt;");
    text.replace(QString::fromUtf8("\""),"&quot;");
    text.replace(QString::fromUtf8("ä"),"&auml;");
    text.replace(QString::fromUtf8("ö"),"&ouml;");
    text.replace(QString::fromUtf8("ü"),"&uuml;");
    text.replace(QString::fromUtf8("Ä"),"&Auml;");
    text.replace(QString::fromUtf8("Ö"),"&Ouml;");
    text.replace(QString::fromUtf8("Ü"),"&Uuml;");
    text.replace(QString::fromUtf8("ß"),"&szlig;");
    text.replace(QString::fromUtf8("€"),"&euro;");
    text.replace(QString::fromUtf8("§"),"&sect;");
    text.replace(QString::fromUtf8("©"),"&copy;");
    text.replace(QString::fromUtf8("®"),"&reg;");
    text.replace(QString::fromUtf8("°"),"&deg;");
    text.replace(QString::fromUtf8("²"),"&sup2;");
    text.replace(QString::fromUtf8("³"),"&sup3;");
    text.replace(QString::fromUtf8("\r\n"),"<br>");
    text.replace(QString::fromUtf8("\r"),"<br>");
    text.replace(QString::fromUtf8("\n"),"<br>");
    return text;
}

QByteArray frmProfile::fromMessage(QString message)
{
    QByteArray text = message.toUtf8();
    text.replace("&auml;","ä");
    text.replace("&ouml;","ö");
    text.replace("&uuml;","ü");
    text.replace("&Auml;","Ä");
    text.replace("&Ouml;","Ö");
    text.replace("&Uuml;","Ü");
    text.replace("&szlig;","ß");
    text.replace("&euro;","€");
    text.replace("&sect;","§");
    text.replace("&copy;","©");
    text.replace("&reg;","®");
    text.replace("&deg;","°");
    text.replace("&sup2;","²");
    text.replace("&sup3;","³");
    text.replace("<br>","\n");
    text.replace("&quot;","\"");
    text.replace("&lt;","<");
    text.replace("&gt;",">");
    text.replace("&amp;","&");
    return text;
}

void frmProfile::on_cmdShowClients_clicked()
{
    QString message;
    message.append(QApplication::tr("Clients of %1").arg(nick) + "\n");
    int curlen = 0;
    int maxlen = maps.length();
    while (curlen != maxlen)
    {
        bool ht = false;
        QMap<QString,QString> map = maps.at(curlen);
        message.append("\n");
        if (map.contains("system"))
        {
            if (ht)
            {
                message.append(", ");
            }
            else
            {
                ht = true;
            }
            message.append(QApplication::tr("System") + ": " + map["system"]);
        }
        if (map.contains("version"))
        {
            if (ht)
            {
                message.append(", ");
            }
            else
            {
                ht = true;
            }
            message.append(QApplication::tr("Version") + ": " + map["version"]);
        }
        if (map.contains("ip"))
        {
            if (ht)
            {
                message.append(", ");
            }
            else
            {
                ht = true;
            }
            message.append(QApplication::tr("IP") + ": " + map["ip"]);
        }
        curlen++;
    }
    QMessageBox::information(this,QApplication::tr("Clients"),message);
}

void frmProfile::setMaps(QList<QMap<QString, QString> > newMaps)
{
    maps = newMaps;
    if (newMaps.length() >= 1)
    {
        ui->cmdShowClients->setEnabled(true);
    }
    ui->labClients->setText(QApplication::tr("Clients: %1").arg(QString::number(newMaps.length())));
}


void frmProfile::on_bbOptions_clicked(QAbstractButton *button)
{
    if (ui->bbOptions->buttonRole(button) == QDialogButtonBox::ApplyRole)
    {
        on_cmdOK_clicked();
    }
    else if (ui->bbOptions->buttonRole(button) == QDialogButtonBox::RejectRole)
    {
        on_cmdAbort_clicked();
    }
}

void frmProfile::on_cmdAvatar_clicked()
{
    frmLogin *login = (frmLogin*)form;

    avatarDialog = new QDialog(this);
    avatarDialog->setWindowFlags(avatarDialog->windowFlags()^Qt::WindowContextHelpButtonHint);
    avatarDialog->setWindowTitle(QApplication::tr("Avatar"));
    avatarDialog->setMinimumSize(200,188);
    avatarDialog->setMaximumSize(200,188);
    avatarLabel = new KPTLabel(avatarDialog);
    avatarLabel->setGeometry(33,0,128,128);

    // Avatar Label Image
#ifdef QT4
    QString msgPath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation) + "/.kmsg";
    msgPath = msgPath.replace("\\","/");
    msgPath = msgPath.replace("//","/");
    QDir dir;
    dir.mkpath(msgPath);
#elif defined(QT5)
    QString msgPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.kmsg";
    msgPath = msgPath.replace("\\","/");
    msgPath = msgPath.replace("//","/");
    QDir dir;
    dir.mkpath(msgPath);
#endif
    QString imgAvatar = login->getUserAvatar();
    QString avatarPath = msgPath + "/" + imgAvatar + ".km";
    if (QFile::exists(avatarPath))
    {
        QFile *avatarFile = new QFile();
        avatarFile->setFileName(avatarPath);
        if (avatarFile->open(QFile::ReadOnly))
        {
            QByteArray avatarArray = avatarFile->readAll();
            QString avatarFormat = avatarArray.left(2);
            if (avatarFormat == "KM")
            {
                avatarArray.remove(0,2);
                QByteArray versionArray = avatarArray.left(1);
                int version = 0;
                version = versionArray.toHex().toInt();
                avatarArray.remove(0,1);
                if (version >= 10)
                {
                    avatarArray = qUncompress(avatarArray);
                    QPixmap avatarPixmap = QPixmap::fromImage(QImage::fromData(avatarArray));
                    avatarFile->close();
                    avatarFile->deleteLater();
                    if (!avatarPixmap.isNull())
                    {
                        avatarLabel->setPixmap(avatarPixmap);
                    }
                    else
                    {
                        qDebug() << "Failed to load Avatar" << imgAvatar;
                        QFile::remove(avatarPath);
                    }
                }
                else
                {
                    qDebug() << "To old Version Avatar" << imgAvatar;
                    avatarFile->close();
                    avatarFile->deleteLater();
                    QFile::remove(avatarPath);
                }
            }
            else
            {
                qDebug() << "Not KM Format Avatar" << imgAvatar;
                avatarFile->close();
                avatarFile->deleteLater();
                QFile::remove(avatarPath);
            }
        }
    }

    // Rest of Avatar Dialog

    avatarChangeButton = new KPTPushButton(avatarDialog);
    avatarChangeButton->setText(QApplication::tr("Change Avatar"));
    avatarChangeButton->setGeometry(0,128,200,30);
    avatarChangeButton->setAutoDefault(false);
    avatarChangeButton->setDefault(false);
    connect(avatarChangeButton,SIGNAL(clicked()),this,SLOT(selectAvatar()));

    avatarApplyButton = new KPTPushButton(avatarDialog);
    avatarApplyButton->setText(QApplication::tr("Apply Avatar"));
    avatarApplyButton->setGeometry(0,128,200,30);
    avatarApplyButton->setVisible(false);
    connect(avatarApplyButton,SIGNAL(clicked()),this,SLOT(uploadAvatar()));

    avatarCloseButton = new KPTPushButton(avatarDialog);
    avatarCloseButton->setText(QApplication::tr("Close"));
    avatarCloseButton->setGeometry(0,158,200,30);
    avatarCloseButton->setAutoDefault(true);
    avatarCloseButton->setDefault(true);
    connect(avatarCloseButton,SIGNAL(clicked()),avatarDialog,SLOT(close()));

    avatarDialog->showNormal();
    avatarDialog->exec();
    avatarDialog->deleteLater();

}

void frmProfile::selectAvatar()
{
    // Read Filter
    QString defaultFilter = "Images (";
    int countFormat = 0;
    foreach(QByteArray imgFormat, QImageReader::supportedImageFormats())
    {
        if (countFormat != 0)
        {
            defaultFilter += " ";
        }
        countFormat++;
        defaultFilter += "*." + QString::fromUtf8(imgFormat);
    }
    defaultFilter += ")";

    // Select File
    QString fileName = KPTFileDialog::getOpenFileName(avatarDialog,QApplication::tr("Select Avatar"),QDir::homePath(),defaultFilter + ";;Portable Network Graphics (*.png);;All files (**)");
    ui->bbOptions->button(QDialogButtonBox::Apply)->setText(QApplication::tr("Change"));
    if (fileName != "")
    {
        if (imgAvatar.load(fileName))
        {
            qDebug() << "Avatar Image loaded";
            if (!imgAvatar.isNull())
            {
                qDebug() << "Avatar Image loaded without problems";
                int ah = imgAvatar.height();
                int aw = imgAvatar.width();
                if (ah > aw)
                {
                    imgAvatar = imgAvatar.scaledToWidth(128,Qt::SmoothTransformation);
                    imgAvatar = imgAvatar.copy(0,0,128,128);
                }
                else if (aw > ah)
                {
                    imgAvatar = imgAvatar.scaledToHeight(128,Qt::SmoothTransformation);
                    imgAvatar = imgAvatar.copy(0,0,128,128);
                }
                else
                {
                    imgAvatar = imgAvatar.scaled(128,128,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
                }
                avatarLabel->setPixmap(QPixmap::fromImage(imgAvatar));

                avatarChangeButton->setVisible(false);
                avatarApplyButton->setVisible(true);
                avatarCloseButton->setAutoDefault(false);
                avatarCloseButton->setDefault(false);
                avatarApplyButton->setAutoDefault(true);
                avatarApplyButton->setDefault(true);

            }
        }
        else
        {
            QMessageBox::warning(avatarDialog,QApplication::tr("Change Avatar"),QApplication::tr("Can't load Avatar"));
        }
    }
}

void frmProfile::uploadAvatar()
{
    frmLogin *login = (frmLogin*)form;
    bool success = login->uploadAvatar(imgAvatar);
    if (success)
    {
        login->getUserAvatar();
        avatarDialog->close();
    }
    else
    {
        QMessageBox::warning(avatarDialog,QApplication::tr("Change Avatar"),QApplication::tr("Error uploading Avatar"));
    }
}
